/*
 * Copyright (c) 2016. For Intelligent Group.
 */
package com.intelligent.ispc.client.core.controller;

import com.intelligent.ispc.client.core.validator.UslAndLslDto;
import com.intelligent.ispc.client.core.view.global.MainStateBar;
import com.intelligent.ispc.client.event.*;
import com.intelligent.ispc.client.utils.ApplicationBeanUtils;
import com.intelligent.ispc.client.utils.EventBusUtils;
import com.intelligent.ispc.client.utils.UIException;
import com.intelligent.ispc.common.utils.ApplicationException;
import com.intelligent.ispc.common.utils.ExceptionMessages;
import com.intelligent.ispc.constant.ProcessConstant;
import com.intelligent.ispc.core.dto.*;
import com.intelligent.ispc.core.service.SpcService;
import com.intelligent.ispc.core.service.SystemService;
import com.intelligent.ispc.r.dto.NDStandardDto;
import com.intelligent.ispc.utils.executor.ExecutorPool;
import com.intelligent.ispc.utils.executor.ExecutorTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by tony.yu on 2016/8/25.
 */
@Component
public class SpcController {

    private final Logger logger = LoggerFactory.getLogger(SpcController.class);

    @Autowired
    private SpcService spcService;

    @Autowired
    private SystemService systemService;

    /**
     * To get item analysis data by itemNames
     *
     * @param fileDataDtos      paths of file to analyze
     * @param dynSearchFieldDto describe search conditions
     * @param testItemNameList  item names for statistic
     * @param excludeItems      specific data of test item to exclude
     * @param param             standard param,contains usl ,lsl and unit
     * @param chartNames        names of charts
     */
    public void findData(List<KeyValueDto> fileDataDtos, Map<String, List<DynSearchFieldDto>> dynSearchFieldDto, List<String> testItemNameList,
                         Map<String, List<TestItemDto>> excludeItems, Map<String, NDStandardDto> param, Map<String, List<String>> chartNames) {
        try {
            boolean isWorking = ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isWorking(ProcessConstant.SPC_EXECUTE_TASK);
            if (isWorking) {
                throw new UIException("This task is already working now.");
            }
            EventBusUtils.post(new StatusBarProcessCreateTaskEvent(ProcessConstant.SPC_EXECUTE_TASK));
            ExecutorTask task = new ExecutorTask(ProcessConstant.SPC_EXECUTE_TASK, new ExecutorTask.Work() {
                @Override
                public void execute() {
                    List<SpcResultDto> resultDtos = null;
                    try {
                        resultDtos = spcService.getStatisticResult(fileDataDtos, dynSearchFieldDto, testItemNameList, excludeItems, param, chartNames);
                        logger.debug("SpcController findData is" + resultDtos);
                        if (!ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isProcessTaskEmpty()) {
                            EventBusUtils.post(new ExecutorTaskFinishEvent(ProcessConstant.SPC_EXECUTE_TASK, resultDtos));
                            EventBusUtils.post(new StatusBarProcessFinishTaskEvent(ProcessConstant.SPC_EXECUTE_TASK, false));
                        }
                    } catch (ApplicationException e) {
                        EventBusUtils.post(new StatusBarProcessChangeEvent(ProcessConstant.SPC_EXECUTE_TASK, e.getFullMessage()).level(ProcessConstant.ERROR));
                    }
                }

                @Override
                public void stop() {

                }
            });
            ExecutorPool.submit(task);
        } catch (ApplicationException e) {
            logger.error("SpcController findData error :" + e.getFullMessage());
            EventBusUtils.post(new ThrowExceptionEvent(e.getFullMessage()));
        } catch (Exception e) {
            logger.error("SpcController findData error :" + e.getMessage());
            EventBusUtils.post(new ThrowExceptionEvent(ExceptionMessages.ERR_20001, e.getMessage()));
        }
    }

    /**
     * Get testItem names list
     *
     * @param fileNames csv file names
     */
    public void findTestItemNames(List<String> fileNames) {
        try {
            boolean isWorking = ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isWorking(ProcessConstant.SPC_DECODE_FILE);
            if (isWorking) {
                throw new UIException("This task is already working now.");
            }
            EventBusUtils.post(new StatusBarProcessCreateTaskEvent(ProcessConstant.SPC_DECODE_FILE));
            ExecutorTask task = new ExecutorTask(ProcessConstant.SPC_DECODE_FILE, new ExecutorTask.Work() {
                @Override
                public void execute() {
                    try {
                        FieldDataSourceDto dto = spcService.findFieldDataSource(fileNames);
                        if (!ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isProcessTaskEmpty()) {
                            EventBusUtils.post(new ExecutorTaskFinishEvent(ProcessConstant.SPC_DECODE_FILE, dto));
                            EventBusUtils.post(new StatusBarProcessFinishTaskEvent(ProcessConstant.SPC_DECODE_FILE, false));
                        }
                    } catch (ApplicationException e) {
                        EventBusUtils.post(new StatusBarProcessChangeEvent(ProcessConstant.SPC_DECODE_FILE, e.getFullMessage()).level(ProcessConstant.ERROR));
                    }
                }

                @Override
                public void stop() {

                }
            });
            ExecutorPool.submit(task);
        } catch (ApplicationException e) {
            logger.error("SpcController findTestItemNames error :" + e.getFullMessage());
            EventBusUtils.post(new ThrowExceptionEvent(e.getFullMessage()));
        } catch (Exception e) {
            logger.error("SpcController findTestItemNames error :" + e.getMessage());
            EventBusUtils.post(new ThrowExceptionEvent(ExceptionMessages.ERR_20001, e.getMessage()));
        }
    }

    /**
     * Export all charts
     *
     * @param files        csv file names
     * @param searchKeys   search conditions
     * @param testItemName test item names
     * @param chartNames   chart names
     * @param chartDtoMap  chart datas
     * @param excludeItems unSelected test data
     * @param param        the USL and LSL's current value
     */
    public void exportAllChart(List<KeyValueDto> files, List<DynSearchFieldDto> searchKeys, String testItemName, List<String> chartNames,
                               Map<String, ChartDto> chartDtoMap, List<TestItemDto> excludeItems, NDStandardDto param) {
        boolean isWorking = ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isWorking(ProcessConstant.SPC_EXPORT_FILE);
        if (isWorking) {
            throw new UIException("This task is already working now.");
        }
        EventBusUtils.post(new StatusBarProcessCreateTaskEvent(ProcessConstant.SPC_EXPORT_FILE, true));
        ExecutorTask task = new ExecutorTask(ProcessConstant.SPC_EXPORT_FILE, new ExecutorTask.Work() {
            @Override
            public void execute() {
                try {
                    UslAndLslDto uslAndLslDto = new UslAndLslDto();
                    if (param != null) {
                        if (param.getUslValue() != null) {
                            uslAndLslDto.setUslValue(param.getUslValue().toString());
                        }
                        if (param.getLslValue() != null) {
                            uslAndLslDto.setLslValue(param.getLslValue().toString());
                        }
                    }
                    spcService.exportAllChart(files, searchKeys, testItemName, chartNames, chartDtoMap, excludeItems, param);
                    if (!ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isProcessTaskEmpty()) {
                        EventBusUtils.post(new ExecutorTaskFinishEvent(ProcessConstant.SPC_EXPORT_FILE, null));
                        EventBusUtils.post(new StatusBarProcessFinishTaskEvent(ProcessConstant.SPC_EXPORT_FILE));
                    }
                } catch (ApplicationException e) {
                    EventBusUtils.post(new StatusBarProcessChangeEvent(ProcessConstant.SPC_EXPORT_FILE, e.getFullMessage()).level(ProcessConstant.ERROR));
                } catch (Exception e) {
                    EventBusUtils.post(new ThrowExceptionEvent(ExceptionMessages.ERR_20001, e.getMessage()));
                }
            }

            @Override
            public void stop() {

            }
        });
        ExecutorPool.submit(task);
    }

    /**
     * Export multiply NDChart
     *
     * @param files        csv file names
     * @param searchKeys   search conditions
     * @param testItemName test item names
     */
    public void exportMultipleNDChart(List<KeyValueDto> files, List<DynSearchFieldDto> searchKeys, List<String> testItemName) {
        boolean isWorking = ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isWorking(ProcessConstant.SPC_EXPORT_FILE);
        if (isWorking) {
            throw new UIException("This task is already working now.");
        }
        EventBusUtils.post(new StatusBarProcessCreateTaskEvent(ProcessConstant.SPC_EXPORT_FILE, true));
        ExecutorTask task = new ExecutorTask(ProcessConstant.SPC_EXPORT_FILE, new ExecutorTask.Work() {
            @Override
            public void execute() {
                try {
                    spcService.exportMultipleNDChart(files, searchKeys, testItemName);
                    if (!ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isProcessTaskEmpty()) {
                        EventBusUtils.post(new ExecutorTaskFinishEvent(ProcessConstant.SPC_EXPORT_FILE, null));
                        EventBusUtils.post(new StatusBarProcessFinishTaskEvent(ProcessConstant.SPC_EXPORT_FILE));
                    }
                } catch (ApplicationException e) {
                    EventBusUtils.post(new StatusBarProcessChangeEvent(ProcessConstant.SPC_EXPORT_FILE, e.getFullMessage()).level(ProcessConstant.ERROR));
                } catch (Exception e) {
                    EventBusUtils.post(new ThrowExceptionEvent(ExceptionMessages.ERR_20001, e.getMessage()));
                }
            }

            @Override
            public void stop() {

            }
        });
        ExecutorPool.submit(task);
    }

    /**
     * Export SPC charts
     *
     * @param files        csv file names
     * @param searchKeys   search conditions
     * @param testItemName test item names
     * @param chartNames   chart names
     * @param guidesParams had auxiliary line's data
     * @param excludeItems unSelected data
     * @param param        current USL、LSL and Group's value
     */
    public void exportChart(List<KeyValueDto> files, Map<String, List<DynSearchFieldDto>> searchKeys, List<String> testItemName, Map<String, List<String>> chartNames,
                            Map<String, Map<String, ChartDto>> guidesParams, Map<String, List<TestItemDto>> excludeItems, Map<String, NDStandardDto> param) {
        boolean isWorking = ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isWorking(ProcessConstant.SPC_EXPORT_FILE);
        if (isWorking) {
            throw new UIException("This task is already working now.");
        }
        EventBusUtils.post(new StatusBarProcessCreateTaskEvent(ProcessConstant.SPC_EXPORT_FILE, true));
        ExecutorTask task = new ExecutorTask(ProcessConstant.SPC_EXPORT_FILE, new ExecutorTask.Work() {
            @Override
            public void execute() {
                try {
                    spcService.exportMultipleItem(files, searchKeys, testItemName, chartNames, guidesParams, excludeItems, param);
                    if (!ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isProcessTaskEmpty()) {
                        EventBusUtils.post(new ExecutorTaskFinishEvent(ProcessConstant.SPC_EXPORT_FILE, null));
                        EventBusUtils.post(new StatusBarProcessFinishTaskEvent(ProcessConstant.SPC_EXPORT_FILE));
                    }
                } catch (ApplicationException e) {
                    EventBusUtils.post(new StatusBarProcessChangeEvent(ProcessConstant.SPC_EXPORT_FILE, e.getFullMessage()).level(ProcessConstant.ERROR));
                } catch (Exception e) {
                    EventBusUtils.post(new ThrowExceptionEvent(ExceptionMessages.ERR_20001, e.getMessage()));
                }
            }

            @Override
            public void stop() {

            }
        });
        ExecutorPool.submit(task);
    }


    /**
     * Export SPC charts
     *
     * @param files         csv file names
     * @param testItemNames testItem names
     * @param searchKeys    search conditions
     * @param chartNames    chart names
     * @param guidesParams  had auxiliary line's data
     * @param excludeItems  unSelected data
     * @param params         current USL、LSL and Group's value
     */
    public void exportChart(List<KeyValueDto> files, List<String> testItemNames, List<DynSearchFieldDto> searchKeys, List<String> chartNames,
                            Map<String, ChartDto> guidesParams, Map<String, List<TestItemDto>> excludeItems, Map<String, NDStandardDto> params) {
        boolean isWorking = ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isWorking(ProcessConstant.SPC_EXPORT_FILE);
        if (isWorking) {
            throw new UIException("This task is already working now.");
        }
        EventBusUtils.post(new StatusBarProcessCreateTaskEvent(ProcessConstant.SPC_EXPORT_FILE, true));
        ExecutorTask task = new ExecutorTask(ProcessConstant.SPC_EXPORT_FILE, new ExecutorTask.Work() {
            @Override
            public void execute() {
                try {
                    Map<String, SpcExportDto> exportDtoMap = new LinkedHashMap<>();
                    for (String testItemName : testItemNames) {
                        SpcExportDto spcExportDto = new SpcExportDto();
                        spcExportDto.setSearchKeys(searchKeys);
                        spcExportDto.setChartNames(chartNames);
                        spcExportDto.setGuidesParams(guidesParams);
                        if (excludeItems.containsKey(testItemName)) {
                            spcExportDto.setExcludeItems(excludeItems.get(testItemName));
                        }
                        if (params.containsKey(testItemName)) {
                            spcExportDto.setParam(params.get(testItemName));
                        }
                        exportDtoMap.put(testItemName, spcExportDto);
                    }
                    spcService.exportMultipleItem(files, exportDtoMap);
                    if (!ApplicationBeanUtils.getBean(MainStateBar.class).getProcessPanel().isProcessTaskEmpty()) {
                        EventBusUtils.post(new ExecutorTaskFinishEvent(ProcessConstant.SPC_EXPORT_FILE, null));
                        EventBusUtils.post(new StatusBarProcessFinishTaskEvent(ProcessConstant.SPC_EXPORT_FILE));
                    }
                } catch (ApplicationException e) {
                    EventBusUtils.post(new StatusBarProcessChangeEvent(ProcessConstant.SPC_EXPORT_FILE, e.getFullMessage()).level(ProcessConstant.ERROR));
                } catch (Exception e) {
                    EventBusUtils.post(new ThrowExceptionEvent(ExceptionMessages.ERR_20001, e.getMessage()));
                }
            }

            @Override
            public void stop() {

            }
        });
        ExecutorPool.submit(task);
    }

    /**
     * Get SpcConfig's data
     *
     * @return spcConfigDto
     */
    public SpcConfigDto findSpcConfig() {
        SpcConfigDto spcConfigDto = null;
        try {
            spcConfigDto = systemService.findSpcConfigs().get(0);
        } catch (ApplicationException e) {
            logger.error("SpcController findSpcConfig error :" + e.getFullMessage());
            EventBusUtils.post(new ThrowExceptionEvent(e.getFullMessage()));
        } catch (Exception e) {
            logger.error("SpcController findSpcConfig error :" + e.getMessage());
            EventBusUtils.post(new ThrowExceptionEvent(ExceptionMessages.ERR_20001, e.getMessage()));
        }
        return spcConfigDto;
    }
}
